package com.markbuikema.juliana32.util.facebook;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;

import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Request.GraphUserCallback;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.Session.StatusCallback;
import com.facebook.SessionState;
import com.facebook.model.GraphObject;
import com.facebook.model.GraphUser;
import com.markbuikema.juliana32.model.nieuws.Comment;
import com.markbuikema.juliana32.model.nieuws.FacebookNieuwsItem;
import com.markbuikema.juliana32.model.teams.FacebookEvent;
import com.markbuikema.juliana32.util.Constants;
import com.markbuikema.juliana32.util.DateTimeUtils;

public class FacebookManager {
	private static FacebookManager instance;

	static final String ACCESS_TOKEN = "281741915275542|uc5YqxhvQIBkMga9srZNMx_3UBU";
	static final String FACEBOOK_TIMELINE_PHOTOS_ALBUM_ID = "339047466152992";
	static final String JULIANA_PAGE_ID = "294105307313875";
	static final String GRAPH_PATH_FEED = JULIANA_PAGE_ID + "/posts";
	static final String GRAPH_PATH_COMMENTS = "/comments";
	static final int FACEBOOK_POST_COUNT = 245;

	private Activity activity;
	private StatusCallback statusCallback;
	private FacebookUser user;

	private FacebookManager() {
	}

	public static FacebookManager getInstance() {
		if (instance == null) {
			instance = new FacebookManager();
		}
		return instance;
	}

	public void onStart() {
		Session.getActiveSession().addCallback(statusCallback);
	}

	public void onStop() {
		Session.getActiveSession().removeCallback(statusCallback);
		activity = null;
	}

	public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
		this.activity = activity;
		Session.getActiveSession().onActivityResult(activity, requestCode, resultCode, data);
	}

	public void onClickLogin(Fragment fragment) {
		Session session = Session.getActiveSession();
		if (!session.isOpened() && !session.isClosed()) {
			session.openForRead(new Session.OpenRequest(activity).setCallback(statusCallback));
		} else {
			Session.openActiveSession(activity, fragment, true, statusCallback);
		}
	}

	public List<FacebookNieuwsItem> getFacebookFeed() {

		Bundle params = new Bundle();
		params.putString("access_token", ACCESS_TOKEN);
		params.putString("limit", Integer.toString(FACEBOOK_POST_COUNT));

		Request request = new Request(null, GRAPH_PATH_FEED, params, HttpMethod.GET);
		Response response = request.executeAndWait();

		GraphObject object = response.getGraphObject();

		if (object == null)
			return new ArrayList<FacebookNieuwsItem>();
		else {
			JSONObject json = object.getInnerJSONObject();

			return FacebookParser.parseFeed(json);
		}
	}

	public FacebookManager onCreate(Bundle savedInstanceState, Activity activity, StatusCallback statusCallback) {

		this.activity = activity;
		this.statusCallback = statusCallback;

		Session session = Session.getActiveSession();
		if (session == null) {
			if (savedInstanceState != null) {
				session = Session.restoreSession(activity, null, statusCallback, savedInstanceState);
			}
			if (session == null) {
				session = new Session(activity);
			}
			Session.setActiveSession(session);
			if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
				session.openForRead(new Session.OpenRequest(activity).setPermissions("basic_info").setCallback(statusCallback));
			}
		}

		return this;
	}

	public void onSaveInstanceState(Bundle outState) {
		Session session = Session.getActiveSession();
		Session.saveSession(session, outState);
	}

	public void getUser(final FacebookProfileCallback callback) {
		if (user == null) {
			Request userRequest = Request.newMeRequest(Session.getActiveSession(), new GraphUserCallback() {

				@Override
				public void onCompleted(GraphUser user, Response response) {

					if (user != null)
						FacebookManager.this.user = new FacebookUser(user.getName(), user.getId());

					callback.onFacebookProfileRetrieved(FacebookManager.this.user);
				}
			});
			userRequest.executeAsync();

		} else {
			callback.onFacebookProfileRetrieved(user);
		}
	}

	public static class PhotoGetter extends AsyncTask<FacebookNieuwsItem, Void, List<String>> {

		@Override
		protected List<String> doInBackground(FacebookNieuwsItem... params) {
			try {
				FacebookNieuwsItem item = params[0];
				return params == null ? null : getInstance().getFacebookPhotos(item.getAlbumId(), item.getDefaultPhoto());
			} catch (IndexOutOfBoundsException e) {
				return null;
			}
		}
	}

	private List<String> getFacebookPhotos(String albumId, String defaultPhoto) {
		List<String> photos = new ArrayList<String>();

		if (albumId == null) {
			photos.add(defaultPhoto);
			return photos;
		}
		try {

			Bundle params = new Bundle();
			params.putString("access_token", ACCESS_TOKEN);

			Request request = new Request(null, albumId + "/photos", params, HttpMethod.GET);
			Response response = request.executeAndWait();

			GraphObject go = response.getGraphObject();
			if (go != null) {
				JSONObject json = go.getInnerJSONObject();

				JSONArray data = json.getJSONArray("data");
				for (int i = 0; i < data.length(); i++)
					photos.add(data.getJSONObject(i).getString("id"));
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}

		return photos;
	}

	@Deprecated
	public static class CommentLoader extends AsyncTask<String, Comment, List<Comment>> {

		@Override
		protected List<Comment> doInBackground(String... id) {
			List<Comment> output = new ArrayList<Comment>();

			Bundle params = new Bundle();
			params.putString("access_token", ACCESS_TOKEN);

			Request req = new Request(null, id[0] + GRAPH_PATH_COMMENTS, params, HttpMethod.GET);
			Response response = req.executeAndWait();

			JSONObject responseJSON = response.getGraphObject().getInnerJSONObject();
			try {
				JSONArray data = responseJSON.getJSONArray("data");
				for (int c = 0; c < data.length(); c++) {
					output.add(processCommentJSON(data.getJSONObject(c)));
				}
			} catch (JSONException e) {

				return output;
			}

			return output;
		}

		private Comment processCommentJSON(JSONObject data) {
			String id;
			try {
				id = data.getString("id");
			} catch (JSONException e) {
				id = "";
			}

			String name;
			try {
				name = data.getJSONObject("from").getString("name");
			} catch (JSONException e) {
				name = "Fout bij het laden van de naam";
			}

			String userId = null;
			try {
				userId = data.getJSONObject("from").getString("id");
			} catch (JSONException e1) {
				e1.printStackTrace();
			}

			String text;
			try {
				text = data.getString("message");
			} catch (JSONException e) {
				text = "Fout bij het laden van de reactie";
			}

			String dateString;
			try {
				dateString = data.getString("created_time"); // 2013-08-23T14:55:26+0000
			} catch (JSONException e) {
				dateString = "2019-12-31T23:59:59+0000";
			}

			Comment comment = new Comment(id, name, userId, text, dateString);
			return comment;
		}
	}

	public List<FacebookEvent> getJulianaEvents(int week) {

		Bundle params = new Bundle();
		params.putString("access_token", ACCESS_TOKEN);

		Request request = new Request(null, "/" + JULIANA_PAGE_ID + "/events", params, HttpMethod.GET);
		Response response = request.executeAndWait();

		JSONObject json = response.getGraphObject().getInnerJSONObject();

		List<FacebookEvent> allEvents = FacebookParser.parseEvents(json);
		List<FacebookEvent> weekEvents = new ArrayList<FacebookEvent>();

		GregorianCalendar gc = new GregorianCalendar();
		gc.set(GregorianCalendar.MONTH, 0);
		gc.set(GregorianCalendar.DAY_OF_MONTH, 1);
		gc.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SUNDAY);

		long firstDay = gc.getTimeInMillis() + (week - 2) * Constants.WEEK_MILLISECONDS;
		long lastDay = firstDay + Constants.WEEK_MILLISECONDS;

		for (FacebookEvent event : allEvents) {
			if (event.getDate() > firstDay && event.getDate() < lastDay)
				weekEvents.add(event);
		}

		return weekEvents;

	}

	public interface FacebookProfileCallback {
		public void onFacebookProfileRetrieved(FacebookUser facebookUser);
	}

}